package com.g001.model;

import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;

import com.g001.enums.CharacterType;
import com.g001.enums.MessagePositionType;
import com.g001.model.abilities.Ability;
import com.g001.model.abilities.Health;
import com.g001.model.abilities.Magic;
import com.g001.model.abilities.Power;
import com.g001.model.abilities.Shield;
import com.g001.model.abilities.StrikeBack;
import com.g001.model.powers.Action;
import com.g001.model.powers.AttackAction;
import com.g001.model.powers.MessageAction;
import com.g001.util.CachedResourceLoader;

public abstract class GCharacter extends GEntity {
	
	private static final int INDEX_HEALTH = 0;
	private static final int INDEX_STRIKE_BACK = 1;
	private static final int INDEX_MAGIC = 2;
	private static final int INDEX_SHIELD = 3;
	private static final int MAX3 = 3;
	
	protected CharacterType characterType;
//	protected boolean look2left;
	protected List<Ability> abilities;
	protected String name;
	protected int xp;

	List<Power> powers;
	// if the character is currently playing
	protected boolean playing;
	
	protected Vector2f interfacePosition;
	protected Animation currentAnimation;
	
	private List<Action> actions;
	protected Action currentAction;
	
	protected Action previousAction;
	protected int counter;
	protected float x;
 
	@Override
	public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
		// character's name
		CachedResourceLoader.font.drawString(interfacePosition.x, interfacePosition.y -30, name);
		for(Power p : powers) {
			p.render(container, game, g);
		}
		// display the action that is currently in the queue.
		if(currentAction!=null && !currentAction.isFinished()) {
			currentAction.render(container, game, g);
		} 
	}
	
	public void addAction(final Action action){
		System.out.println("action="+action+" previousAction="+previousAction+" action.getType()="+action.getType());
		if(previousAction == null || action.getType() != previousAction.getType()) {
			System.out.println("==>"+action+" count:"+counter);
			previousAction = action;
			actions.add(action);
			if(previousAction==null)
				counter = 1; 
			else
				counter = 0;
		} else if(action.getType() == previousAction.getType()){
			counter++;
			System.out.println("**>"+action+" count:"+counter);
			if(counter>MAX3) {
				previousAction.setBonus(counter-MAX3+1);
				System.out.println("**> bonus:"+previousAction.getBonus());
				//actions.add(new MessageAction("EXTRA TURN", MessagePositionType.CENTER, 800, MessageAction.BIG_FONT));
			}
		}

	}
	
	
	/**
	 * true if all animations are over
	 * @return
	 */
	public boolean isReady(){
		if(currentAction == null) return true;
		else
		return currentAction.isFinished() && actions.size()==0;
	}

	
	 
	@Override
	public void update(GameContainer container, StateBasedGame game, int delta)
			throws SlickException {		
		currentAnimation.update(delta);
		for(Power p : powers) {
			p.update(container, game, delta);
		}
		// update the display of first action
		if(currentAction != null && !currentAction.isFinished()){
			currentAction.update(container, game, delta);
		} else {
			System.out.println("*** reset ***");
			previousAction = currentAction;
			currentAction = null;
			counter = 0;
			// reset animation of character
			setCurrentAnimation(characterType.getIdleAnim());
		}
		if(currentAction instanceof AttackAction){
			x += 0.2f * delta * (characterType.isRight2left()?-1:1);
		} else {
			x = position.x ;
		}
	}
	

	public boolean isDead() {
		return getHeath().getValue()<=0;
	}
	
	public void addAbility(Ability lightStrike,GameContainer container){
		float deltaY = 0;
		if(abilities == null) abilities = new ArrayList<Ability>();
		int count = abilities.size();
		lightStrike.getPosition().add(new Vector2f(95f * (count%3), deltaY+64f*(count/3)));
		abilities.add(lightStrike);
		container.getInput().addMouseListener(lightStrike);
	}

	public String getName() {
		return name;
	}

	public boolean isPlaying() {
		return playing;
	}

	public void setPlaying(boolean playing) {
		this.playing = playing;
	}

	public Health getHeath() {
		return (Health)powers.get(INDEX_HEALTH);
	}


	public void setActions(List<Action> actions) {
		this.actions = actions;
	}

	public List<Action> getActions() {
		return actions;
	}

	public Shield getShield() {
		return (Shield)powers.get(INDEX_SHIELD);
	}
	
	public Magic getMagic() {
		return (Magic)powers.get(INDEX_MAGIC);
	}
	
	public StrikeBack getStrikeBack() {
		return (StrikeBack)powers.get(INDEX_STRIKE_BACK);
	}
	
	

	public void startAnimations() {
		if(currentAction==null && actions!=null && actions.size()>0) {
			// get & remove the action from the list
			currentAction = actions.remove(0);
			currentAction.action();
		}
	}

	public Animation getCurrentAnimation() {
		return currentAnimation;
	}

	public void setCurrentAnimation(Animation currentAnimation) {
		this.currentAnimation = currentAnimation;
	}

	public CharacterType getCharacterType() {
		return characterType;
	}

	public void setCharacterType(CharacterType characterType) {
		this.characterType = characterType;
	}

}
